package com.codepoetics.protonpack.collectors;
import org.junit.Test;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.IntStream;
import static java.util.stream.Collectors.toList;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
public class CompletableFuturesTest {
private static final Random random = new Random();
@Test
public void collectsValuesFromCompletableFutures() throws ExecutionException, InterruptedException {
ExecutorService threadPool = Executors.newFixedThreadPool(10);
CompletableFuture<List<Integer>> integers = IntStream.range(0, 1000)
.mapToObj(i -> CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(random.nextInt(100));
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return i;
}, threadPool))
.collect(CompletableFutures.toFutureList());
assertThat(
integers.get(),
equalTo(IntStream.range(0, 1000).mapToObj(Integer::valueOf).collect(toList())));
}
@Test
public void failsFastOnAnyFutureFailure() throws ExecutionException, InterruptedException {
ExecutorService threadPool = Executors.newFixedThreadPool(10);
IllegalStateException expectedException = new IllegalStateException("19! Aaargh!");
CompletableFuture<List<Integer>> integers = IntStream.range(0, 1000)
.mapToObj(i -> CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(random.nextInt(100));
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (i == 19) {
throw expectedException;
}
return i;
}, threadPool))
.collect(CompletableFutures.toFutureList());
AtomicReference<Throwable> exc = new AtomicReference<>();
integers.handle((success, failure) -> { exc.set(failure.getCause()); return null; }).get();
assertThat(exc.get(), equalTo(expectedException));
}
@Test
public void reducesFutureInts() throws ExecutionException, InterruptedException {
ExecutorService threadPool = Executors.newFixedThreadPool(10);
final CompletableFuture<Optional<Integer>> collected = IntStream.range(1, 1000)
.parallel()
.mapToObj(i -> CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(random.nextInt(100));
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return i;
}, threadPool))
.collect(CompletableFutures.reducing((l, r) -> l + r));
assertThat(collected.get().get(), equalTo(499500));
}
}